home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * CagdCrvt.c - curvature computation of curves and surfaces. *
- *******************************************************************************
- * Written by Gershon Elber, March 93. *
- ******************************************************************************/
-
- #include "cagd_loc.h"
-
- #define MAX_POS_REF_ITERATION 20
-
- /******************************************************************************
- * Computes a scalar curve representing the curvature of a planar curve. *
- * The given curve is assumed to be planar and only its x and y coordinates *
- * are considered. *
- * Then the curvature k is equal to *
- * . .. . .. *
- * X Y - Y X *
- * k = ------------- *
- * .2 .2 3/2 *
- * ( X + Y ) *
- * Since we cannot represent k because of the square root, we compute and *
- * represent k^2. *
- ******************************************************************************/
- CagdCrvStruct *CagdCrvCurvatureSqr(CagdCrvStruct *Crv)
- {
- CagdBType
- IsRational = CAGD_IS_RATIONAL_CRV(Crv);
- CagdCrvStruct *Crv1W, *Crv1X, *Crv1Y, *Crv1Z,
- *Crv2W, *Crv2X, *Crv2Y, *Crv2Z,
- *CTmp1, *CTmp2, *CTmp3, *Numer, *Denom, *CurvatureSqr,
- *Crv1Deriv = CagdCrvDerive(Crv),
- *Crv2Deriv = CagdCrvDerive(Crv1Deriv);
-
- CagdCrvSplitScalar(Crv1Deriv, &Crv1W, &Crv1X, &Crv1Y, &Crv1Z);
- CagdCrvSplitScalar(Crv2Deriv, &Crv2W, &Crv2X, &Crv2Y, &Crv2Z);
- CagdCrvFree(Crv1Deriv);
- CagdCrvFree(Crv2Deriv);
-
- CTmp1 = CagdCrvMult(Crv1X, Crv2Y);
- CTmp2 = CagdCrvMult(Crv2X, Crv1Y);
- CTmp3 = CagdCrvSub(CTmp1, CTmp2);
- CagdCrvFree(CTmp1);
- CagdCrvFree(CTmp2);
- Numer = CagdCrvMult(CTmp3, CTmp3);
- CagdCrvFree(CTmp3);
-
- CTmp1 = CagdCrvMult(Crv1X, Crv1X);
- CTmp2 = CagdCrvMult(Crv1Y, Crv1Y);
- CTmp3 = CagdCrvAdd(CTmp1, CTmp2);
- CagdCrvFree(CTmp1);
- CagdCrvFree(CTmp2);
- CTmp1 = CagdCrvMult(CTmp3, CTmp3);
- Denom = CagdCrvMult(CTmp1, CTmp3);
- CagdCrvFree(CTmp1);
- CagdCrvFree(CTmp3);
- if (IsRational) {
- CTmp1 = CagdCrvMult(Crv1W, Crv1W);
- CTmp2 = CagdCrvMult(CTmp1, CTmp1);
- CTmp3 = CagdCrvMult(CTmp2, Numer);
- CagdCrvFree(CTmp1);
- CagdCrvFree(CTmp2);
- CagdCrvFree(Numer);
- Numer = CTmp3;
-
- CTmp1 = CagdCrvMult(Crv2W, Crv2W);
- CTmp2 = CagdCrvMult(CTmp1, Denom);
- CagdCrvFree(CTmp1);
- CagdCrvFree(Denom);
- Denom = CTmp2;
- }
- if (CAGD_IS_BSPLINE_CRV(Denom)) {
- CTmp1 = CagdMakePosCrvCtlPolyPos(Denom);
- CagdCrvFree(Denom);
- Denom = CTmp1;
- }
-
- CagdMakeCrvsCompatible(&Denom, &Numer, TRUE, TRUE);
- CurvatureSqr = CagdCrvMergeScalar(Denom, Numer, NULL, NULL);
- CagdCrvFree(Denom);
- CagdCrvFree(Numer);
-
- CagdCrvFree(Crv1X);
- CagdCrvFree(Crv1Y);
- CagdCrvFree(Crv2X);
- CagdCrvFree(Crv2Y);
- if (Crv1Z)
- CagdCrvFree(Crv1Z);
- if (Crv2Z)
- CagdCrvFree(Crv2Z);
- if (Crv1W)
- CagdCrvFree(Crv1W);
- if (Crv2W)
- CagdCrvFree(Crv2W);
-
- return CurvatureSqr;
- }
-
- /******************************************************************************
- * Computes a vectior field curve representing the curvature of a curve, in *
- * the normal direction, that is kN. *
- * . .. . . .. . *
- * C x C C ( C x C ) x C *
- * kN = kB x N = ----- x ----- = -------------- *
- * . 3 . . 4 *
- * | C | | C | | C | *
- ******************************************************************************/
- CagdCrvStruct *CagdCrvCurvatureNormal(CagdCrvStruct *Crv)
- {
- CagdBType
- IsRational = CAGD_IS_RATIONAL_CRV(Crv);
- CagdCrvStruct *CrvW, *CrvX, *CrvY, *CrvZ,
- *CTmp, *Numer, *Denom, *CurvatureNormal,
- *Crv1Deriv = CagdCrvDerive(Crv),
- *Crv2Deriv = CagdCrvDerive(Crv1Deriv);
-
- CTmp = CagdCrvCrossProd(Crv1Deriv, Crv2Deriv);
- CagdCrvFree(Crv2Deriv);
- Numer = CagdCrvCrossProd(CTmp, Crv1Deriv);
- CagdCrvFree(CTmp);
- CagdCrvSplitScalar(Numer, &CrvW, &CrvX, &CrvY, &CrvZ);
- CagdCrvFree(Numer);
-
- CTmp = CagdCrvDotProd(Crv1Deriv, Crv1Deriv);
- CagdCrvFree(Crv1Deriv);
- Denom = CagdCrvMult(CTmp, CTmp);
-
- if (IsRational) {
- CagdCrvStruct *DenomCrvW, *DenomCrvX, *DenomCrvY, *DenomCrvZ;
-
- CagdCrvSplitScalar(Denom,
- &DenomCrvW, &DenomCrvX, &DenomCrvY, &DenomCrvZ);
- CagdCrvFree(Denom);
-
- CTmp = CagdCrvMult(CrvW, DenomCrvX);
- CagdCrvFree(CrvW);
- CrvW = CTmp;
-
- CTmp = CagdCrvMult(CrvX, DenomCrvW);
- CagdCrvFree(CrvX);
- CrvX = CTmp;
-
- CTmp = CagdCrvMult(CrvY, DenomCrvW);
- CagdCrvFree(CrvY);
- CrvY = CTmp;
-
- CTmp = CagdCrvMult(CrvZ, DenomCrvW);
- CagdCrvFree(CrvZ);
- CrvZ = CTmp;
-
- CagdCrvFree(DenomCrvW);
- CagdCrvFree(DenomCrvX);
-
- CurvatureNormal = CagdCrvMult(CTmp, Numer);
- CagdCrvFree(CTmp);
- }
- else {
- CagdMakeCrvsCompatible(&Denom, &CrvX, TRUE, TRUE);
- CagdMakeCrvsCompatible(&Denom, &CrvY, TRUE, TRUE);
- CagdMakeCrvsCompatible(&Denom, &CrvZ, TRUE, TRUE);
- CrvW = Denom;
- }
- CurvatureNormal = CagdCrvMergeScalar(CrvW, CrvX, CrvY, CrvZ);
- CagdCrvFree(CrvX);
- CagdCrvFree(CrvY);
- CagdCrvFree(CrvZ);
- CagdCrvFree(CrvW);
-
- return CurvatureNormal;
- }
-
- /******************************************************************************
- * Computes a scalar curve representing the curvature sign of a planar curve. *
- * The given curve is assumed to be planar and only its x and y coordinates *
- * are considered. *
- * Then the curvature sign is equal to *
- * . .. . .. *
- * s = X Y - Y X *
- ******************************************************************************/
- CagdCrvStruct *CagdCrvCurvatureSign(CagdCrvStruct *Crv)
- {
- CagdBType
- IsRational = CAGD_IS_RATIONAL_CRV(Crv);
- CagdCrvStruct *Crv1W, *Crv1X, *Crv1Y, *Crv1Z,
- *Crv2W, *Crv2X, *Crv2Y, *Crv2Z,
- *CTmp1, *CTmp2, *Numer, *Denom, *CurvatureSign,
- *Crv1Deriv = CagdCrvDerive(Crv),
- *Crv2Deriv = CagdCrvDerive(Crv1Deriv);
-
- CagdCrvSplitScalar(Crv1Deriv, &Crv1W, &Crv1X, &Crv1Y, &Crv1Z);
- CagdCrvSplitScalar(Crv2Deriv, &Crv2W, &Crv2X, &Crv2Y, &Crv2Z);
- CagdCrvFree(Crv1Deriv);
- CagdCrvFree(Crv2Deriv);
-
- CTmp1 = CagdCrvMult(Crv1X, Crv2Y);
- CTmp2 = CagdCrvMult(Crv2X, Crv1Y);
- Numer = CagdCrvSub(CTmp1, CTmp2);
- CagdCrvFree(CTmp1);
- CagdCrvFree(CTmp2);
-
- if (IsRational) {
- Denom = CagdCrvMult(Crv1W, Crv2W);
-
- CagdMakeCrvsCompatible(&Denom, &Numer, TRUE, TRUE);
- CurvatureSign = CagdCrvMergeScalar(Denom, Numer, NULL, NULL);
- CagdCrvFree(Denom);
- CagdCrvFree(Numer);
- }
- else {
- CurvatureSign = Numer;
- }
-
- CagdCrvFree(Crv1X);
- CagdCrvFree(Crv1Y);
- CagdCrvFree(Crv2X);
- CagdCrvFree(Crv2Y);
- if (Crv1Z)
- CagdCrvFree(Crv1Z);
- if (Crv2Z)
- CagdCrvFree(Crv2Z);
- if (Crv1W)
- CagdCrvFree(Crv1W);
- if (Crv2W)
- CagdCrvFree(Crv2W);
-
- return CurvatureSign;
- }
-
- /******************************************************************************
- * Given a curve that is positive, refine it until all its control points has *
- * positive coefficients. Always returns a Bspline curve. *
- ******************************************************************************/
- CagdCrvStruct *CagdMakePosCrvCtlPolyPos(CagdCrvStruct *OrigCrv)
- {
- int l;
- CagdCrvStruct
- *RefCrv = NULL;
-
- switch (OrigCrv -> GType) {
- case CAGD_CBEZIER_TYPE:
- RefCrv = CnvrtBezier2BsplineCrv(OrigCrv);
- break;
- case CAGD_CBSPLINE_TYPE:
- RefCrv = CagdCrvCopy(OrigCrv);
- break;
- case CAGD_CPOWER_TYPE:
- default:
- FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
- break;
- }
-
- for (l = 0; l < MAX_POS_REF_ITERATION; l++) {
- int i, j,
- Len = RefCrv -> Length,
- Order = RefCrv -> Order;
- CagdRType
- *KV = RefCrv -> KnotVector,
- *Nodes = BspKnotNodes(KV, Len + Order, Order),
- *Pts = RefCrv -> Points[1];
-
- for (i = j = 0; i < Len; i++) {
- if (Pts[i] < 0) /* To refine at negative control points. */
- Nodes[j++] = Nodes[i];
- }
- if (j == 0) {
- IritFree(Nodes);
- break;
- }
- else {
- CagdCrvStruct
- *NewCrv = CagdCrvRefineAtParams(RefCrv, FALSE, Nodes, j);
-
- CagdCrvFree(RefCrv);
- RefCrv = NewCrv;
- IritFree(Nodes);
- }
- }
-
- return RefCrv;
- }
-
- /******************************************************************************
- * Given a planar curve, find all its inflection points by find the zero set *
- * of the sign of the curvature function. *
- ******************************************************************************/
- CagdPtStruct *CagdCrvInflectionPts(CagdCrvStruct *Crv, CagdRType Epsilon)
- {
- CagdCrvStruct
- *CrvtrSign = CagdCrvCurvatureSign(Crv);
- CagdPtStruct
- *InflectionPts = CagdCrvZeroSet(CrvtrSign, 1, Epsilon);
-
- CagdCrvFree(CrvtrSign);
-
- return InflectionPts;
- }
-
- /******************************************************************************
- * Given a planar curve, find all its extreme curvatrue points by find the *
- * extreme set of the curvature function. *
- ******************************************************************************/
- CagdPtStruct *CagdCrvExtremCrvtrPts(CagdCrvStruct *Crv, CagdRType Epsilon)
- {
- if (CAGD_NUM_OF_PT_COORD(Crv -> PType) == 2) {
- CagdCrvStruct
- *CrvtrSqrCrv = CagdCrvCurvatureSqr(Crv);
- CagdPtStruct
- *ExtremCrvtrPts = CagdCrvExtremSet(CrvtrSqrCrv, 1, Epsilon);
-
- CagdCrvFree(CrvtrSqrCrv);
-
- return ExtremCrvtrPts;
- }
- else if (CAGD_NUM_OF_PT_COORD(Crv -> PType) == 3) {
- CagdCrvStruct
- *CrvtrNormalCrv = CagdCrvCurvatureNormal(Crv),
- *CrvtrMag = CagdCrvDotProd(CrvtrNormalCrv, CrvtrNormalCrv);
- CagdPtStruct
- *ExtremCrvtrPts = CagdCrvExtremSet(CrvtrMag, 1, Epsilon);
-
- CagdCrvFree(CrvtrNormalCrv);
- CagdCrvFree(CrvtrMag);
-
- return ExtremCrvtrPts;
- }
- else {
- FATAL_ERROR(CAGD_ERR_ONLY_2D_OR_3D);
- return NULL;
- }
- }
-
-